﻿using HalconDotNet;
using HWindow_Tool.Control;
using LD.BC;
using LD.Host;
using LD.PLC;
using System;
using System.IO;
using System.Web.UI;
using System.Windows.Forms;
using YTE.Control;
using System.Linq;
using System.Reflection;
using ViewWindow.Config;

namespace LD.Vision
{
    public partial class FrmCalibByBoard : FrmBase
    {
        private AbsCamera camera;
        //private HHomMat2D mat2d;
        private int[] calib_x = new int[] { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
        private int[] calib_y = new int[] { 1, 1, 1, 0, 0, 0, -1, -1, -1 };
        private int[] calib_r = new int[] { 4, 2, 0, -2, -4 };
        private float errorVal = 0;
        private FrmTemplate frmTemplate = null;
        private CalibrationModel calibrationModel = null;
        private string filePath = Path.Combine(Appbus.BasePath, "Vision\\Calibration\\Board");
        public FrmCalibByBoard()
        {
            InitializeComponent();
            this.Load += FrmCalibByBoard_Load;
        }
        private void FrmCalibByBoard_Load(object sender, EventArgs e)
        {
            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);

            foreach (var item in CameraFactory.Instance.CameraList)
            {
                this.cob_camera.Items.Add(item.Key);
            }

            frmTemplate = new FrmTemplate();
            frmTemplate.Dock = DockStyle.Fill;
            frmTemplate.TopLevel = false;
            frmTemplate.FormBorderStyle = FormBorderStyle.None;
            frmTemplate.Show();
            this.splitContainer1.Panel2.Controls.Add(frmTemplate);

            if (calibrationModel == null)
                calibrationModel = new CalibrationModel();
        }
        private void cob_camera_SelectedIndexChanged(object sender, EventArgs e)
        {
            string cameraName = this.cob_camera.Text;
            if (CameraFactory.Instance.CameraList.ContainsKey(cameraName))
            {
                camera = CameraFactory.Instance.CameraList[cameraName];

                if (camera != null)
                {

                }
            }
        }
        private void UiUpdate()
        {
            this.dgv_data.Rows.Clear();
            int len = this.calibrationModel.Px.Length;
            for (int i = 0; i < len; i++)
            {
                this.dgv_data.Rows.Add(i + 1,
                    this.calibrationModel.Wx[i],
                    this.calibrationModel.Wy[i],
                    this.calibrationModel.Px[i],
                    this.calibrationModel.Py[i]);
            }
        }
        private void materialButton2_Click(object sender, EventArgs e)
        {
            if (camera != null)
            {
                camera.StartGrab();
            }
        }
        private void materialButton1_Click(object sender, EventArgs e)
        {
            if (camera != null)
            {
                if (camera.Trigger())
                    this.frmTemplate.HImage = camera.Image;
            }
        }
        private void materialButton3_Click(object sender, EventArgs e)
        {
            using (var ofd = new OpenFileDialog())
            {
                ofd.Title = "请选择图片";
                //ofd.Filter = "(*.bmp)|*.bmp|(*.jpg) | *.jpg";
                ofd.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
          "*.tiff; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
                ofd.RestoreDirectory = true;
                ofd.Multiselect = false;
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string fileName = ofd.FileName;
                    this.txt_imagePath.Text = fileName;

                    this.frmTemplate.HImage = new HImage(fileName);
                }
            }
        }
        private void btn_startCalib_Click(object sender, EventArgs e)
        {
            double[] wx = new double[9];
            double[] wy = new double[9];
            double[] px = new double[9];
            double[] py = new double[9];
            this.dgv_data.Rows.Clear();
            try
            {

                //移动到标定位（中心位）
                //开始标定
                //获取标定位轴信息
                var curPoint = Appbus.PartNo.Config.AxisPoint.Where(p => p.Name == "标定位").FirstOrDefault();
                if (curPoint == null)
                    return;

                //9点
                for (int i = 0; i < calib_x.Length; i++)
                {
                    foreach (var item in curPoint.AxisPointDic)
                    {
                        if (item.Key == AxisType.X.ToString())
                        {
                            BcFactory.Instance.Control.Move_Ration(item.Value.AxisId, calib_x[i]);   //x相对运动
                        }
                        if (item.Key == AxisType.Y.ToString())
                        {
                            BcFactory.Instance.Control.Move_Ration(item.Value.AxisId, calib_y[i]);   //y相对运动
                        }

                        BcFactory.Instance.Control.WaitAxisComplete(item.Value.AxisId);              //等待完成
                    }
                    //Get世界坐标
                    var axisX = curPoint.AxisPointDic.Where(p => p.Key == AxisType.X.ToString()).FirstOrDefault();
                    var axisY = curPoint.AxisPointDic.Where(p => p.Key == AxisType.Y.ToString()).FirstOrDefault();
                    double x = BcFactory.Instance.Control.GetAxisPosition(axisX.Value.AxisId);
                    double y = BcFactory.Instance.Control.GetAxisPosition(axisY.Value.AxisId);
                    //拍照
                    var camera = CameraFactory.Instance.CameraList.Where(p => p.Key == this.cob_camera.Text).FirstOrDefault();
                    bool isSuccess = camera.Value.Trigger();
                    if (isSuccess)
                    {
                        camera.Value.Image.WriteImage("bmp", 0, Path.Combine(filePath, i + ".bmp"));

                        this.frmTemplate.HImage = camera.Value.Image;
                        isSuccess = this.frmTemplate.GetTemplate();
                        if (isSuccess)
                        {
                            wx[i] = x;
                            wy[i] = y;
                            px[i] = this.frmTemplate.结果.Row;
                            py[i] = this.frmTemplate.结果.Column;
                            this.dgv_data.Rows.Add(this.dgv_data.Rows.Count + 1, x, y, this.frmTemplate.结果.Row, this.frmTemplate.结果.Column);
                        }
                        else
                            return;
                    }
                    else
                    {
                        Log4.Warr($"相机【{this.cob_camera.Text}】拍照失败");
                        return;
                    }
                }

                //转换坐标
                calibrationModel.HHomMat2D.VectorToHomMat2d(new HTuple(wx), new HTuple(wy), new HTuple(px), new HTuple(py));

                //记录数据
                Array.Copy(wx, 0, calibrationModel.Wx, 0, 9);
                Array.Copy(wy, 0, calibrationModel.Wy, 0, 9);
                Array.Copy(px, 0, calibrationModel.Px, 0, 9);
                Array.Copy(py, 0, calibrationModel.Py, 0, 9);
            }
            catch (Exception ex)
            {
                Log4.Error(ex);
            }
        }
        private void btn_calib5_Click(object sender, EventArgs e)
        {
            if (this.dgv_data.Rows.Count == 0)
                return;

            Circle circle = new Circle();
            double[] wx = new double[5];
            double[] wy = new double[5];
            double[] px = new double[5];
            double[] py = new double[5];
            try
            {
                //移动到标定位（中心位）
                //开始标定
                //获取标定位轴信息
                var curPoint = Appbus.PartNo.Config.AxisPoint.Where(p => p.Name == "标定位").FirstOrDefault();
                if (curPoint == null)
                    return;

                //5点
                for (int i = 0; i < calib_r.Length; i++)
                {
                    foreach (var item in curPoint.AxisPointDic)
                    {
                        if (item.Key == AxisType.R.ToString())
                        {
                            BcFactory.Instance.Control.Move_Ration(item.Value.AxisId, calib_r[i]);   //r相对运动
                        }
                        BcFactory.Instance.Control.WaitAxisComplete(item.Value.AxisId);              //等待完成
                    }
                    //世界坐标
                    var axisX = curPoint.AxisPointDic.Where(p => p.Key == AxisType.X.ToString()).FirstOrDefault();
                    var axisY = curPoint.AxisPointDic.Where(p => p.Key == AxisType.Y.ToString()).FirstOrDefault();
                    double x = BcFactory.Instance.Control.GetAxisPosition(axisX.Value.AxisId);
                    double y = BcFactory.Instance.Control.GetAxisPosition(axisY.Value.AxisId);
                    //拍照
                    var camera = CameraFactory.Instance.CameraList.Where(p => p.Key == this.cob_camera.Text).FirstOrDefault();
                    bool isSuccess = camera.Value.Trigger();
                    if (isSuccess)
                    {
                        camera.Value.Image.WriteImage("bmp", 0, Path.Combine(filePath, i + 10 + ".bmp"));
                        this.frmTemplate.HImage = camera.Value.Image;
                        isSuccess = this.frmTemplate.GetTemplate();
                        if (isSuccess)
                        {
                            px[i] = this.frmTemplate.结果.Row;
                            py[i] = this.frmTemplate.结果.Column;
                        }
                        else
                            return;
                    }
                    else
                    {
                        Log4.Warr($"相机【{this.cob_camera.Text}】拍照失败");
                        return;
                    }
                }

                //5点世界坐标数据拟合圆
                //计算世界坐标圆心半径
                for (int i = 0; i < wy.Length; i++)
                {
                    //转换为世界坐标，世界坐标画圆
                    var wxr = calibrationModel.HHomMat2D.AffineTransPoint2d((double)px[i], py[i], out var wyr);
                    wx[i] = wxr;
                    wy[i] = wyr;
                    this.dgv_data.Rows.Add(this.dgv_data.Rows.Count + 1, wxr, wyr, px[i], py[i]);
                }

                //5点数据
                //拟合圆
                HXLDCont hXLDCont = new HXLDCont();
                hXLDCont.GenContourPolygonXld(wx, wy);

                //拟合参数
                string algorithm = "geotukey";
                int maxNumPoints = -1;
                double maxClosureDist = 0;
                int clippingEndPoints = 0;
                int iterations = 3;
                double clippingFactor = 2.0;
                hXLDCont.FitCircleContourXld(algorithm,
                                             maxNumPoints,
                                             maxClosureDist,
                                             clippingEndPoints,
                                             iterations,
                                             clippingFactor,
                                            out double row1,
                                            out var column1,
                                            out double radius,
                                            out var startPhi,
                                            out var endPhi,
                                            out var pointOrder
                                            );
                circle.Row = row1;
                circle.column1 = column1;
                circle.Radius = radius;
                circle.StartPhi = startPhi;
                circle.EndPhi = endPhi;
                circle.PointOrder = pointOrder;

                //记录数据
                calibrationModel.Circle = circle;

                Array.Copy(wx, 0, calibrationModel.Wx, 9, 5);
                Array.Copy(wy, 0, calibrationModel.Wy, 9, 5);
                Array.Copy(px, 0, calibrationModel.Px, 9, 5);
                Array.Copy(py, 0, calibrationModel.Py, 9, 5);
            }
            catch (Exception ex)
            {
                Log4.Error(ex);
            }
        }
        private void btn_calib1_Click(object sender, EventArgs e)
        {

        }
        public void Save()
        {
            //弹窗保存
            using (var ofd = new SaveFileDialog())
            {
                ofd.Title = "保存数据";
                //ofd.Filter = "(*.bmp)|*.bmp|(*.jpg) | *.jpg";
                ofd.Filter = "(*.ldc)|*.ldc;";
                ofd.RestoreDirectory = true;
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string fileName = ofd.FileName;

                    calibrationModel.Save(fileName);
                }
            }
        }
        public void Input()
        {
            //弹窗
            using (var ofd = new OpenFileDialog())
            {
                ofd.Title = "打开数据";
                //ofd.Filter = "(*.bmp)|*.bmp|(*.jpg) | *.jpg";
                ofd.Filter = "(*.ldc)|*.ldc;";
                ofd.RestoreDirectory = true;
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string fileName = ofd.FileName;

                    calibrationModel = JsonSerializeHelper.Load<CalibrationModel>(filePath);
                    UiUpdate();
                }
            }
        }
    }
}
